import numpy as np
import pandas as pd
from networkx import DiGraph, topological_sort
import networkx as nx
import pickle

# 知识点名称列表
nodes = [
    "选择1", "选择2", "选择3", "选择4", "选择5", "选择6", "选择7", "选择8", "选择9", "选择10",
    "填空1", "填空2", "填空3", "填空4", "填空5", "填空6",
    "计算1", "计算2", "证明1", "证明2", "综合应用1", "综合应用2"
]

# 读取去环后的邻接矩阵
df = pd.read_excel('去环邻接矩阵.xlsx', index_col=0)
df.index = nodes
df.columns = nodes
matrix = df.values

print("实际行索引：", list(df.index))
print("实际列索引：", list(df.columns))

# 检查缺失项
missing_rows = [node for node in nodes if node not in df.index]
missing_cols = [node for node in nodes if node not in df.columns]
print("缺失的行：", missing_rows)
print("缺失的列：", missing_cols)

# 构建依赖图
G = DiGraph()
G.add_nodes_from(nodes)
for i, row in enumerate(matrix):
    for j, val in enumerate(row):
        if val == 1:
            # 添加边：行知识点 → 列知识点（先导 → 后继）
            G.add_edge(nodes[i], nodes[j])

# 保存networkx DiGraph对象为gpickle文件
with open('knowledge_graph.gpickle', 'wb') as f:
    pickle.dump(G, f)

# 拓扑排序并反转
top_order = list(topological_sort(G))
sorted_nodes = top_order[::-1]  # 反转顺序

# 生成新的行列索引映射
node_index = {node: idx for idx, node in enumerate(sorted_nodes)}

# 调整矩阵行列
sorted_matrix = np.zeros_like(matrix)
for i in range(len(sorted_nodes)):
    for j in range(len(sorted_nodes)):
        # 原矩阵的行列对应新的索引
        sorted_matrix[i, j] = matrix[nodes.index(sorted_nodes[i]), nodes.index(sorted_nodes[j])]

# 输出到txt文件
with open('topo.txt', 'w', encoding='utf-8') as f:
    f.write("调整后的行/列顺序:\n")
    f.write(", ".join(sorted_nodes) + "\n\n")
    f.write("矩阵数据:\n")
    for row in sorted_matrix:
        f.write(", ".join(map(str, row)) + "\n")

relations = []
for i, row in df.iterrows():
    for j, val in row.items():
        if val == 1:
            relations.append(f"{i} -> {j}")

# 输出到txt文件
with open('graph_edges.txt', 'w', encoding='utf-8') as f:
    for i, row in df.iterrows():
        for j, val in row.items():
            if val == 1:
                f.write(f"{i} {j}\n")  # 用空格分隔，或用逗号/制表符

# 计算分层（每个节点的层级）
layer_dict = {}
for node in nx.topological_sort(G):
    preds = list(G.predecessors(node))
    if not preds:
        layer_dict[node] = 0
    else:
        layer_dict[node] = max(layer_dict[p] for p in preds) + 1

# 按层输出
layers = {}
for node, layer in layer_dict.items():
    layers.setdefault(layer, []).append(node)

with open('分层结构.txt', 'w', encoding='utf-8') as f:
    for layer in sorted(layers):
        f.write(f"第{layer+1}层: {', '.join(layers[layer])}\n")

with open('knowledge_graph.gpickle', 'rb') as f:
    G = pickle.load(f)